using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GameFramework;
using UnityGameFramework.Runtime;
using LS.Tools;

namespace LS.GameSystem
{
    public abstract class GameSystemBase : IGameSystem
    {
        private FrameInvoker m_NextFrameInvoker;

        public virtual string Name { get; set; }

        public abstract int Priority { get; }

        public virtual void Init()
        {
            
        }

        public virtual void Shutdown()
        {
            StopAllCoroutine();
            ClearNextFrame();
            if (m_NextFrameInvoker != null)
            {
                ReferencePool.Release(m_NextFrameInvoker);
            }
            m_NextFrameInvoker = null;
        }

        public virtual void Update(float deltaSeconds, float realSeconds)
        {
            UpdateNextFrameActions();
        }
        
        public virtual void FixedUpdate(float deltaSeconds, float realSeconds)
        {
            
        }

        public virtual void UpdateSeconds(int seconds)
        {
            
        }

        public virtual void UpdateRealSeconds(int realSeconds)
        {

        }

        public CoroutineComponent.CoroutineHolder StartCoroutine(IEnumerator enumerator)
        {
            return LSEntry.Coroutine.StartCoroutine(this, enumerator);
        }

        public void StopCoroutine(Coroutine coroutine)
        {
            LSEntry.Coroutine?.StopCoroutine(coroutine);
        }

        public void StopAllCoroutine()
        {
            LSEntry.Coroutine?.StopCoroutine(this);
        }

        public void InvokeNextFrame(Action act)
        {
            if (act == null)
            {
                return;
            }

            if (m_NextFrameInvoker == null)
            {
                m_NextFrameInvoker = ReferencePool.Acquire<FrameInvoker>();
            }
            m_NextFrameInvoker.Add(act);
        }

        public void CancelNextFrame(Action act)
        {
            m_NextFrameInvoker?.Remove(act);
        }

        public void ClearNextFrame()
        {
            m_NextFrameInvoker?.Clear();
        }

        private void UpdateNextFrameActions()
        {
            m_NextFrameInvoker?.UpdateInvoke();
        }
    }
}
